package mcommand;

import java.awt.Shape;
import java.util.ArrayList;

import mcommand.City.TownState;
import mcommand.Missile.MissileState;
import mcommand.MissileBay.MissileBayState;

/**
 * Handles the collision of the user missiles with the enemy missiles. and also
 * handles the collision of the enemy missile with the cities and missile bays
 * 
 * @author Marcel, Christian, Klaus
 */
public class CollisionHandler {

    // defines a new statistics handler
    StatisticsHandler statsHandler;

    /**
     * Constructor gets statsHandler to deliver collision infos.
     * 
     * @param statsHandler statsHandler
     */
    public CollisionHandler(final StatisticsHandler statsHandler) {
        this.statsHandler = statsHandler;
    }

    /**
     * handles the collisions of AllyMissile with EnemyMissile. also handles the
     * collision of EnemyMissile with city and missile bay
     * 
     * @param em em
     * @param am am
     * @param cities cities
     * @param mb mb
     */
    public final void update(final ArrayList<EnemyMissile> em,
            final ArrayList<AllyMissile> am, final ArrayList<City> cities,
            final ArrayList<MissileBay> mb) {
        // Check collision of AllyMissile with EnemyMissile
        for (int i = 0; i < am.size(); i++) {
            AllyMissile aMissile = am.get(i);

            // if that missile is exploding
            if (aMissile.isExploding()) {

                // gets the explosion shape
                Shape expCircle = aMissile.getExplosionShape();

                // for every enemy missile
                for (int j = 0; j < em.size(); j++) {
                    EnemyMissile eMissile = em.get(j);

                    // if the explosion shape contains the position of the enemy
                    // missile
                    if (expCircle.contains(eMissile.getX(), eMissile.getY())) {

                        // calls the method to handle the collision
                        handleCollisionOf(eMissile);
                    }
                }
            }
        }

        // Check collision of EnemyMissile with city and missile bay
        // for every enemy missile
        for (int i = 0; i < em.size(); i++) {
            EnemyMissile eMissile = em.get(i);

            // if enemy missile is exploding
            if (eMissile.isExploding()) {

                // gets the explosion shape
                Shape expCircle = eMissile.getExplosionShape();

                // for every city
                for (int j = 0; j < cities.size(); j++) {

                    // if the explosion city intersects the city rectangle
                    if (expCircle.intersects(cities.get(j).
                            getCityRectangle())) {

                        // handles the collision of the city
                        handleCollisionOf(cities.get(j));
                    }
                }
                // for every missile bay
                for (int j = 0; j < mb.size(); j++) {

                    // if the explosion intersects the missile bay rectangle
                    if (expCircle.intersects(mb.get(j).getRectangle())) {

                        // handles the missile bay collision
                        handleCollisionOf(mb.get(j));
                    }
                }
            }
        }
    }

    /**
     * Sets the state of the missile to EXPLODING_OUT if AllyMissile hits
     * EnemyMissile. Adds 1 point for every frame both missiles intersect.
     *
     * @param eMissile eMissile
     */
    private void handleCollisionOf(final EnemyMissile eMissile) {
        // sets the missile state to EXPLODING_OUT
        eMissile.setState(MissileState.EXPLODING_OUT);

        // adds 1 point
        Board.addPoints(1);

        // if the missile is not counted yet, it will
        // be now counted and the counted state is set true
        if (!eMissile.isAlreadyCounted()) {
            statsHandler.rocketHit();

            eMissile.setCounted(true);
        }
    }

    /**
     * Sets the state of the city to DESTROYED if EnemyMissile hits City.
     *
     * @param city city
     */
    private void handleCollisionOf(final City city) {
        city.setState(TownState.DESTROYED);
    }

    /**
     * Sets the state of the missile bay to DESTROYED if EnemyMissile hits
     * MissileBay. Sets the left rockets for that missile bay to 0
     *
     * @param missileBay missileBAy
     */
    private void handleCollisionOf(final MissileBay missileBay) {
        missileBay.setState(MissileBayState.DESTROYED);
        missileBay.setRocketCount(0);
    }
}
